from server import db, api_auth, user_opt
from flask import jsonify, Blueprint, request, g
from server.model.order import Order, refund_wechat_order, OrderStatus
from server.model import set_field, query_by_field
from sqlalchemy import or_
import math

r_order = Blueprint('order', __name__)
exclude_data = {'pay_status', 'order_no', 'actual_paid', 'security_code', 'total_fee'}


@r_order.route('', methods=['GET'])
@api_auth.login_required
def get_orders():
    """
    @@@
    #### Args: {
                page: 1,
                limit: 20,
                filter: {},
                start_time: "2021-09-10",
                end_time: "2021-09-12",
            }
    #### Returns::
            {
                'code': 20000,
                'items': [u.to_dict() for u in order_list],
            }
    """
    page = request.args.get('page', type=int, default=1)
    limit = request.args.get('limit', type=int, default=20)
    start_time = request.args.get('start_time')
    end_time = request.args.get('end_time')
    query_filter = request.args.get('filter')
    key_word = request.args.get('key_word')

    try:

        order_list = Order.query

        if query_filter:
            order_list = query_by_field(order_list, query_filter, Order)

        if key_word:
            order_list = order_list.filter(or_(Order.phone.like('%{}%'.format(key_word)), Order.receiver.like('%{}%'.format(key_word)), Order.region.like('%{}%'.format(key_word))))

        if start_time:
            order_list = order_list.filter(db.cast(Order.create_time, db.Date) >= start_time)

        if end_time:
            order_list = order_list.filter(db.cast(Order.create_time, db.Date) <= end_time)
        total = order_list.count()

        order_list = order_list.order_by(Order.create_time.desc()).offset((page - 1) * limit).limit(limit).all()

        return jsonify({
            'code': 20000,
            'message': 'success',
            'items': [u.to_dict() for u in order_list],
            'totalCount': total,
            'TotalPageCount': math.ceil(int(total / limit))
        })
    except Exception as e:
        print("get orders error:", e)

    return jsonify({'code': 50001, 'message': "查询订单时发生错误"})


@r_order.route('', methods=['POST'])
@api_auth.login_required
def add_order():
    """
    @@@
    #### Args:
            {
                region: String(32)    #寄报地区
                province_city: String(127)    #地址
                address: String(127)    #详细住址
                postcode: String(8)    #邮编
                receiver: String(32)    #收货人
                phone: String(16)    #联系电话
                remark: String(127,)    #订单备注
                start_date: DateTime    #起始日期
                end_date: DateTime    #结束日期
                amount: SMALLINT(unsigned=True)    #报纸数量
                charge_standard: String(255)    #收费标准
                buyer: String(32)    #购买主体
                security_code: String(4)    #验证码
            }
    #### Returns::
            {'code': 20000, 'message': "订单添加成功"}
            {'code': 50001, 'message': "添加订单时发生错误"}
    """

    args = request.get_json()

    order = Order()
    try:
        set_field(order, args)
        db.session.add(order)
        db.session.commit()

        user_opt.send({
            "operation": "添加订单",
            "method": "订单管理",
            "params": f'id:{order.id},参数:{args}',
            "user_id": g.user.id,
            "username": g.user.username
        })

        return jsonify({'code': 20000, 'message': "订单添加成功"})
    except Exception as e:
        db.session.rollback()
        print("add order error:", e)

    return jsonify({'code': 50001, 'message': "添加订单时发生错误"})


@r_order.route('/<int:pid>', methods=['DELETE'])
@api_auth.login_required
def remove_order(pid):
    """
        @@@
        #### Args:
                order/id
        #### Returns::
                {'code': 20000, 'message': "订单删除成功"}
                {'code': 50001, 'message': "删除订单时发生错误"}
        """
    try:
        Order.query.filter_by(id=pid).delete()
        db.session.commit()

        user_opt.send({
            "operation": "删除订单",
            "method": "订单管理",
            "params": pid,
            "user_id": g.user.id,
            "username": g.user.username
        })

        return jsonify({'code': 20000, 'message': "订单删除成功"})
    except Exception as e:
        print("remove order error:", e)
        return jsonify({
            'code': 50001,
            'message': "删除订单时发生错误"
        })


@r_order.route('/<int:pid>', methods=['PUT'])
@api_auth.login_required
def edit_order(pid):
    """
    @@@
    #### Args:
           order/id
    #### Returns::
            {'code': 20000, 'message': "订单修改成功"}
            {'code': 50001, 'message': "修改订单时发生错误"}
    """
    args = request.get_json()
    try:
        order = Order.query.filter_by(id=pid).first()
        set_field(order, args, exclude=exclude_data)

        db.session.commit()

        user_opt.send({
            "operation": "修改订单",
            "method": "订单管理",
            "params": f'id:{pid},参数:{args}',
            "user_id": g.user.id,
            "username": g.user.username
        })

        return jsonify({'code': 20000, 'message': "订单修改成功"})
    except Exception as e:
        db.session.rollback()
        print("edit order error:", e)

    return jsonify({'code': 50001, 'message': "修改订单时发生错误"})


@r_order.route('/<int:pid>', methods=['GET'])
@api_auth.login_required
def get_detail(pid):
    """
                    @@@
                    #### Args:
                           order/id
                    #### Returns::
                            {
                                'code': 20000,
                                'items': [u.to_dict() for u in order_list],
                            }
                """
    order = Order.query.filter_by(id=pid).first()
    if not order:
        return jsonify({
            'code': 50002,
            'message': '查询订单不存在'
        })

    return jsonify({
        'code': 20000,
        'message': 'success',
        'items': order.to_dict(),
    })


@r_order.route('/refund', methods=['POST'])
@api_auth.login_required
def refund_order():
    """
    @@@
    #### Args:
            {
                region: String(32)    #寄报地区
            }
    #### Returns::
            {'code': 20000, 'message': "订单添加成功"}
            {'code': 50001, 'message': "添加订单时发生错误"}
    """

    args = request.get_json()
    order_id = args.get('order_id')
    try:
        order = Order.query.filter(Order.id == order_id).one_or_none()
        if not order:
            return jsonify({'code': 50002, 'message': "订单不存在"})
        order.pay_status = OrderStatus.Refunding
        total_fee = int(order.total_fee * 100)
        # total_fee = int(0.01 * 100)
        result = refund_wechat_order(order.order_no, order.id, total_fee, total_fee)
        user_opt.send({
            "operation": "退款订单",
            "method": "订单管理",
            "params": f'id:{order.id},参数:{args}',
            "user_id": g.user.id,
            "username": g.user.username
        })

        return jsonify({'code': 20000, 'message': "订单申请退款成功"})
    except Exception as e:
        db.session.rollback()
        print("order refund error:", e)

    return jsonify({'code': 50001, 'message': "订单退款时发生错误"})


# 监听微信退款回调
@r_order.route('/wechat_refund_notify', methods=['GET', 'POST'])
def wechat_refund_notify():
    from server import WeChat_pay
    from server.model.order import OrderStatus
    result = WeChat_pay.parse_refund_notify_result(request.data)
    print("got quest into wechat_refund_notify...", result)
    out_trade_no = result.get("out_trade_no")
    refund_status = result.get("refund_status")
    paid_fee = result.get("cash_fee")
    # open_id = result.get("openid")
    total_fee = result.get("total_fee")
    print("got to find order by:", out_trade_no)
    order = Order.query.filter(Order.order_no == out_trade_no).one_or_none()
    if order:
        order.pay_status = OrderStatus.RefundSucceed if refund_status == "SUCCESS" else OrderStatus.RefundFail
        db.session.commit()
    return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>"
# 监听微信支付回调


@r_order.route('/wechat_pay_notify', methods=['GET', 'POST'])
def wechat_pay_notify():
    from server import WeChat_pay
    from server.model.order import OrderStatus
    result = WeChat_pay.parse_payment_result(request.data)
    print("got quest into wechat_pay_notify...", result)
    out_trade_no = result.get("out_trade_no")
    result_code = result.get("result_code")
    paid_fee = result.get("cash_fee")
    # open_id = result.get("openid")
    total_fee = result.get("total_fee")
    print("got to find order by:", out_trade_no)
    order = Order.query.filter(Order.order_no == out_trade_no).one_or_none()
    if order:
        order.pay_status = OrderStatus.Paid if result_code == "SUCCESS" else OrderStatus.Cancel
        order.actual_paid = paid_fee
        db.session.commit()

    return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>"
